#include "stdafx.h"
#include "PluginICPopenCV.h"
#include "Utils.h"

#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace PluginOpenCV;


Utils::Utils(void)
{
}


Utils::~Utils(void)
{
}

int Utils::Convert2BorderType(int border)
{
	int rc = cv::BORDER_DEFAULT;

	switch(border)
	{
		case 1:
			rc = cv::BORDER_REPLICATE;
		break;
		case 2:
			rc = cv::BORDER_REFLECT;
		break;
		case 3:
			rc = cv::BORDER_REFLECT_101;
		break;
		case 4:
			rc = cv::BORDER_WRAP;
		break;
		case 5:
			rc = cv::BORDER_CONSTANT;
		break;
		default:
			rc = cv::BORDER_DEFAULT;
		break;
	}
	return rc;
}

bool Utils::GetImagePathFilenames(IImageComputeFn *fn, const char *root, const char *ijc, const char *ijf, const char *imageRef, const char *srcFiletype, const char *dstFiletype, std::string *filenameDstImage, std::string *pathfilenameSrcImage, std::string *pathfilenameDstImage, std::string *pathfilenameDebugImage)
{
	bool rc = false;

	if ((fn == nullptr) || (root == nullptr) || (ijc == nullptr) || (ijf == nullptr) || (imageRef == nullptr) || (srcFiletype == nullptr) || (dstFiletype == nullptr) || (filenameDstImage == nullptr) || (pathfilenameSrcImage == nullptr) || (pathfilenameDstImage == nullptr) || (pathfilenameDebugImage == nullptr))
		MX_SETERROR(MX11227, MxError::InvalidParams, MxError::Abort, MxError::QuietReport, "one or more params are null for SeqNo %d", ((fn != nullptr) ? fn->GetSeqNo() : -1));
	else
	{
		std::string path(root);		//includes PEF
		path += "\\";
		path += fn->GetSubFolderJobs();
		path += "\\";
		path += ijc;
		path += "\\";
		path += ijf;
		path += "\\";

		char seqnoBuff[33 + 1];
		if (_itoa_s(fn->GetSeqNo(), seqnoBuff, 10) != 0)
			MX_SETERROR(MX11227, MxError::CodeDefect, MxError::Abort, MxError::QuietReport, "_itoa_s() failed for SeqNo %d", fn->GetSeqNo());
		else
		{
			filenameDstImage->assign(imageRef);
			filenameDstImage->append(".");
			filenameDstImage->append(seqnoBuff);

			pathfilenameSrcImage->assign(path);
			pathfilenameSrcImage->append(imageRef);
			pathfilenameSrcImage->append(srcFiletype);

			pathfilenameDstImage->assign(path);
			pathfilenameDstImage->append(*filenameDstImage);
			pathfilenameDstImage->append(dstFiletype);

			pathfilenameDebugImage->assign(path);
			pathfilenameDebugImage->append(*filenameDstImage);
			pathfilenameDebugImage->append(".debug");
			pathfilenameDebugImage->append(dstFiletype);

			rc = true;
		}
	}
	return rc;
}

bool Utils::WriteDebugImage(IImageComputeFn *fn, const char *pathfilenameSrcImage, const char *pathfilenameDstImage, const char *pathfilenameDebugImage, const char *arrayPts)
{
	bool rc = false;

	if ((fn == nullptr) || (pathfilenameSrcImage == nullptr) || (pathfilenameDstImage == nullptr) || (pathfilenameDebugImage == nullptr) || (arrayPts == nullptr))
		MX_SETERROR(MX11249, MxError::InvalidParams, MxError::Abort, MxError::VerboseReport, "one or more params is invalid");
	else
	{
		int arrayCnt = 0;
		if (((arrayCnt = fn->ArrayIntsGetSize(arrayPts)) == ArrayInts::Invalid) || (arrayCnt % 2))
			MX_SETERROR(MX11250, MxError::BadUserInput, MxError::Abort, MxError::VerboseReport, "ArrayInts::GetSize(arrayPts) failed or returned odd number %d", arrayCnt);
		else
		{
			if (arrayCnt < 2)
				rc = true;
			else
			{
				int *arrayPtInts = new int[arrayCnt];
				if (arrayPtInts == nullptr)
					MX_SETERROR(MX11251, MxError::System, MxError::Abort, MxError::QuietReport, "arrayPtInts == nullptr - out of memory?");
				else
				{
					if (fn->ArrayIntsConvertStr2Ints(arrayPts, arrayPtInts, arrayCnt, IImageComputeFn::Invalid) == false)
						MX_SETERROR(MX11252, MxError::CodeDefect, MxError::Abort, MxError::QuietReport, "ArrayInts::ConvertStr2Ints(arrayPts) failed");
					else
					{
						int pointCnt = arrayCnt / 2;
						CvPoint  *points = nullptr;

						try
						{
							points = new CvPoint[pointCnt+1];
							if (points == nullptr)
								MX_SETERROR(MX11253, MxError::System, MxError::Abort, MxError::QuietReport, "points == nullptr - out of memory?");
							else
							{
								int y = 0;
								for (int x = 0; x < pointCnt; x++)
								{
									points[x].x = arrayPtInts[y++];
									points[x].y = arrayPtInts[y++];
								}
								points[pointCnt].x = arrayPtInts[0];
								points[pointCnt].y = arrayPtInts[1];

								cv::Mat img = cv::imread(pathfilenameSrcImage, CV_LOAD_IMAGE_ANYDEPTH);
								if (img.data == nullptr)
									MX_SETERROR(MX11254, MxError::BadUserInput, MxError::Abort, MxError::VerboseReport, "unable to open source image=%s", pathfilenameSrcImage);
								else
								{
									if (cv::imwrite(pathfilenameDstImage, img) == false)
										MX_SETERROR(MX11255, MxError::BadUserInput, MxError::Abort, MxError::VerboseReport, "unable to write dest image=%s", pathfilenameDstImage);
									else
									{
										for (int i = 0; i < pointCnt; i++)
										{
											int j = (i + 1) % pointCnt;
											cv::line(img, points[i], points[j], CV_RGB(255, 0, 0), 1, 8, 0);
										}

										if (cv::imwrite(pathfilenameDebugImage, img) == false)
											MX_SETERROR(MX11256, MxError::BadUserInput, MxError::Abort, MxError::VerboseReport, "unable to write debug image=%s", pathfilenameDebugImage);
										else
										{
											rc = true;
										}
									}
								}
							}
						}
						catch (std::exception& e)
						{
							std::string result("[exception msg not found]");
							MX_SETERROR(MX11257, MxError::CodeDefect, MxError::Abort, MxError::QuietReport, "threw exception %s for source image=%s", PluginICPopenCV::GetOpenCVExceptionMsg(e, &result), pathfilenameSrcImage);
						}
						if (points != nullptr)
							delete[] points;
					}
				}
				if (arrayPtInts != nullptr)
					delete[] arrayPtInts;
			}
		}
	}
	return rc;
}